/**
 * @description 下拉框基础组件
 * @date 2024.9.10
 * @author wz
 * @midify 2025.5.15
 * @editor wz
 */
import { _decorator, Component, UITransform, Node, Button, Vec3, find, view, EventHandler, v3, EventTouch, CCString } from "cc";
import { CLoopScroll } from "./CLoopScroll";
import { M_Direction, V_Direction } from "../common/Enum";
const { ccclass, property } = _decorator;

/**
 * 可继承实现自定义下拉菜单
 */
@ccclass('CDropDownBase')
export default abstract class CDropDownBase extends Component {

    /**
     * 滑动ScrollView
     */
    @property({ type: Node, group: 'CDropDownBase' })
    template: Node;

    /**
     * 按钮实例
     */
    @property({ type: Node, group: 'CDropDownBase' })
    item: Node = null;

    @property({ type: [CCString], tooltip: '下拉框Options', displayName: '下拉框Options', group: 'CDropDownBase' })
    optionList: string[] = [];

    @property({ type: [EventHandler], tooltip: '下拉框响应事件对象', displayName: '下拉框响应事件对象', group: 'CDropDownBase' })
    dpEvents: EventHandler[] = []


    /**
     * 显示的临时节点
     */
    private _nodeBg: Node = null;

    /**
     * 当前选项
     */
    private _value: number = 0;

    /**
     * templateY初始位置
     */
    private _templateY: number = 0;

    /**
     * 滚动组件
     */
    private _loopscroll: CLoopScroll = null;

    /**
     * 0:设置 1:向下 2:向上
     */
    private _direction: number = 0;

    /**
     * 是否展开
     */
    get isExpand(): boolean {
        return (!!this._nodeBg) && this._nodeBg.active;
    }

    /**
     * 点击事件回调
     */
    onItemCallback?: (index: number) => void;

    onLoad() {
        //滚动设置
        this._loopscroll = this.template.getComponent(CLoopScroll);
        this._loopscroll.m_direction = M_Direction.VERTICAL;
        this._loopscroll.setUpdateItemCallback(this.updateItemCallback.bind(this));

        //保留初始位置
        this._templateY = this.template.position.y;

        //初始化隐藏
        this.template.active = false;

        //初始化
        this.setOptions(this.optionList);
    }

    onDestroy() {
        if (this._nodeBg)
            this._nodeBg.destroy();
    }

    /**
     * 设置选项
     * @param data 
     * @param isEvent 响应事件
     */
    setOptions(data: string[]) {
        if (data.length == 0) return
        this.optionList = data;
        if (this._value >= data.length)
            this._value = data.length - 1;
        this.setValue(this._value);
    }

    /**
     * 设置初始值
     * @param value 
     */
    setValue(value: number) {
        this._value = value;
        this.updateShow();
    }


    /**
     * 添加按钮事件
     * @param {*} button 
     * @param {*} target 
     * @param {*} component 
     * @param {*} handler 
     * @param {*} customData 
     */
    private addButtonEvent(button: Button, target: Node, component: string, handler: string, customData) {
        let clickEventHandler = new EventHandler();
        clickEventHandler.target = target;
        clickEventHandler.component = component;
        clickEventHandler.handler = handler;
        clickEventHandler.customEventData = customData;
        button.clickEvents.push(clickEventHandler)
    }

    /**
     * 滚动更新回调
     * @param item 
     * @param index 
     * @param data 
     */
    private updateItemCallback(item: Node, index: number, data: any) {
        //重置按钮事件
        let button = item.getComponent(Button);
        button.clickEvents = [];
        //本脚本事件响应
        this.addButtonEvent(button, this.node, 'CDropDownBase', 'onValueEvent', index);

        this.setItem(item, index == this._value, index, data);
    }

    /**
     * 刷新显示
     */
    private updateShow() {
        //更新显示的item
        let itemInfo = this._loopscroll.getValidItemInfo();
        for (let i = 0; i < itemInfo.length; i++) {
            let temp = itemInfo[i];
            let index = temp.index;
            this.setItem(temp.node, index == this._value, index, this.optionList[index])
        }
        this.setDrop(this._value, this.optionList[this._value]);
    }

    /**
     * 数据更新
     * @param {*} sender 
     * @param {*} customData
     */
    private onValueEvent(sender: EventTouch, index: number) {
        this._value = index;

        //响应目标上添加事件
        this.dpEvents.forEach((a: EventHandler) => a.emit([this.node, index]))

        //支持代码直接设置响应事件
        if (this.onItemCallback) {
            this.onItemCallback(index);
        }

        this.updateShow();
        this.onCloseTemplate();
    }

    /**
     * 检查是否超出下屏幕然后向上增加
     */
    private checkOverScreen() {
        let screenView = view.getVisibleSize();
        let count = this.optionList.length;
        let height = this._loopscroll.paddingTop + count * this._loopscroll.itemHeight + (count - 1) * this._loopscroll.spacingY + this._loopscroll.paddingBottom;

        let worldPos = this.template.parent.getComponent(UITransform).convertToWorldSpaceAR(v3(0, this._templateY));
        let posY = this._nodeBg.getComponent(UITransform).convertToNodeSpaceAR(worldPos).y;

        let downDis = posY - height + screenView.height / 2;
        let upDis = screenView.height / 2 - posY - Math.abs(this._templateY * 2) - height;

        let direction = 0;

        if (downDis > 0) {
            this.template.setPosition(new Vec3(this.template.position.x, this._templateY));
            this.template.getComponent(UITransform).anchorY = 1;
            this.template.getComponent(UITransform).height = height;
            direction = 1;
        }
        else if (upDis > 0) {
            this.template.setPosition(new Vec3(this.template.position.x, -this._templateY));
            this.template.getComponent(UITransform).anchorY = 0;
            this.template.getComponent(UITransform).height = height;
            direction = 2;
        }
        else if (downDis >= upDis) {
            this.template.setPosition(new Vec3(this.template.position.x, this._templateY));
            this.template.getComponent(UITransform).anchorY = 1;
            this.template.getComponent(UITransform).height = this.template.position.y + screenView.height / 2;
            direction = 1;
        }
        else {
            this.template.setPosition(new Vec3(this.template.position.x, -this._templateY));
            this.template.getComponent(UITransform).anchorY = 0;
            this.template.getComponent(UITransform).height = screenView.height / 2 - this.template.position.y;
            direction = 2;
        }

        if (this._direction != direction) {
            this._loopscroll.v_direction = direction == 1 ? V_Direction.TOP_TO_BOTTOM : V_Direction.BOTTOM_TO_TOP;
            this._loopscroll.reset();
            this._loopscroll.updateData(this.optionList, 0.1);
            this._loopscroll.scrollToIndex(this._value);
        }
        this._direction = direction;
    }

    /**
     * 显示选择面板
     */
    onShowTemplate() {
        if (!this._nodeBg) {
            let canvas = find('Canvas');
            this._nodeBg = new Node('Dropdown_Bg');
            this._nodeBg.layer = this.node.layer;
            this._nodeBg.setSiblingIndex(1000);

            let button = this._nodeBg.addComponent(Button);
            button.clickEvents = [];
            this.addButtonEvent(button, this.node, 'CDropDown', 'onCloseTemplate', '');

            this._nodeBg.parent = canvas;
            this._nodeBg.position = new Vec3(0, 0);
            this._nodeBg.getComponent(UITransform).width = canvas.getComponent(UITransform).width;
            this._nodeBg.getComponent(UITransform).height = canvas.getComponent(UITransform).height;
        }

        this.checkOverScreen();


        let worldPos = this.template.parent.getComponent(UITransform).convertToWorldSpaceAR(new Vec3(this.template.position.x, this.template.position.y));
        let localPos = this._nodeBg.getComponent(UITransform).convertToNodeSpaceAR(worldPos);

        this.template.parent = this._nodeBg;
        this.template.position = localPos;

        this._nodeBg.active = true;
        this.template.active = true;
    }

    /**
     * 关闭选择面板
     */
    onCloseTemplate() {
        let worldPos = this.template.parent.getComponent(UITransform).convertToWorldSpaceAR(new Vec3(this.template.position.x, this.template.position.y));
        let localPos = this.node.getComponent(UITransform).convertToNodeSpaceAR(worldPos);

        this.template.parent = this.node;
        this.template.position = localPos;

        if (this._nodeBg)
            this._nodeBg.active = false;
        this.template.active = false;
    }



    /**
     * 自定义设置下拉框标题显示
     * @param index
     * @param option 
     */
    abstract setDrop(index: number, option: string)

    /**
     * 自定义设置下拉框item
     * @param item     item实例
     * @param isSel    
     * @param index
     * @param option 
     */
    abstract setItem(item: Node, isSel: boolean, index: number, option: string);

}
